package com.flyqiu.common.tools;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.Date;

/**
 * 日期时间工具类，提供日期时间的格式化、解析及时间差计算等功能。
 */
public class LocalDateTimeTools {

    /**
     * 将Date类型日期格式化为字符串，默认格式为"yyyy-MM-dd HH:mm:ss"。
     *
     * @param date 需要格式化的日期
     * @return 格式化后的日期字符串
     */
    public static String format(Date date) {
        return format(date, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 将Date类型日期格式化为字符串，指定格式。
     *
     * @param date   需要格式化的日期
     * @param format 指定的日期格式
     * @return 格式化后的日期字符串
     */
    public static String format(Date date, String format) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        return simpleDateFormat.format(date);
    }

    /**
     * 将字符串解析为Date类型日期，默认格式为"yyyy-MM-dd HH:mm:ss"。
     *
     * @param dateStr 需要解析的日期字符串
     * @return 解析后的Date对象
     */
    public static Date ofDate(String dateStr) {
        return ofDate(dateStr, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 将字符串解析为Date类型日期，指定格式。
     *
     * @param dateStr 需要解析的日期字符串
     * @param format  指定的日期格式
     * @return 解析后的Date对象
     * @throws RuntimeException 当解析失败时抛出
     */
    public static Date ofDate(String dateStr, String format) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        try {
            return simpleDateFormat.parse(dateStr);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将LocalDate格式化为字符串，默认格式为"yyyy-MM-dd"。
     *
     * @param localDate 需要格式化的LocalDate
     * @return 格式化后的日期字符串
     */
    public static String format(LocalDate localDate) {
        return format(localDate, "yyyy-MM-dd");
    }

    /**
     * 将LocalDate格式化为字符串，指定格式。
     *
     * @param localDate 需要格式化的LocalDate
     * @param format    指定的日期格式
     * @return 格式化后的日期字符串
     */
    public static String format(LocalDate localDate, String format) {
        DateTimeFormatter dfDateTime = DateTimeFormatter.ofPattern(format);
        return dfDateTime.format(localDate);
    }

    /**
     * 将字符串解析为LocalDate，默认格式为"yyyy-MM-dd"。
     *
     * @param date 需要解析的日期字符串
     * @return 解析后的LocalDate对象
     */
    public static LocalDate ofLocalDate(String date) {
        return ofLocalDate(date, "yyyy-MM-dd");
    }

    /**
     * 将字符串解析为LocalDate，指定格式。
     *
     * @param dateStr 需要解析的日期字符串
     * @param format  指定的日期格式
     * @return 解析后的LocalDate对象
     */
    public static LocalDate ofLocalDate(String dateStr, String format) {
        DateTimeFormatter dfDateTime = DateTimeFormatter.ofPattern(format);
        TemporalAccessor parse = dfDateTime.parse(dateStr);
        return LocalDate.from(parse);
    }

    /**
     * 将LocalTime格式化为字符串，默认格式为"HH:mm:ss"。
     *
     * @param time 需要格式化的LocalTime
     * @return 格式化后的时间字符串
     */
    public static String format(LocalTime time) {
        return format(time, "HH:mm:ss");
    }

    /**
     * 将LocalTime格式化为字符串，指定格式。
     *
     * @param time   需要格式化的LocalTime
     * @param format 指定的时间格式
     * @return 格式化后的时间字符串
     */
    public static String format(LocalTime time, String format) {
        DateTimeFormatter dfDateTime = DateTimeFormatter.ofPattern(format);
        return dfDateTime.format(time);
    }

    /**
     * 将字符串解析为LocalTime，默认格式为"HH:mm:ss"。
     *
     * @param localTimeStr 需要解析的时间字符串
     * @return 解析后的LocalTime对象
     */
    public static LocalTime ofLocalTime(String localTimeStr) {
        return ofLocalTime(localTimeStr, "HH:mm:ss");
    }

    /**
     * 将字符串解析为LocalTime，指定格式。
     *
     * @param localTimeStr 需要解析的时间字符串
     * @param format       指定的时间格式
     * @return 解析后的LocalTime对象
     */
    public static LocalTime ofLocalTime(String localTimeStr, String format) {
        DateTimeFormatter dfDateTime = DateTimeFormatter.ofPattern(format);
        TemporalAccessor parse = dfDateTime.parse(localTimeStr);
        return LocalTime.from(parse);
    }

    /**
     * 将LocalDateTime格式化为字符串，默认格式为"yyyy-MM-dd HH:mm:ss"。
     *
     * @param localDateTime 需要格式化的LocalDateTime
     * @return 格式化后的日期时间字符串
     */
    public static String format(LocalDateTime localDateTime) {
        return format(localDateTime, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 声明需要格式化的格式(日期加时间)
     *
     * @param localDateTime LocalDateTime
     * @param format        时间格式
     * @return String
     */
    public static String format(LocalDateTime localDateTime, String format) {
        if (localDateTime == null) return null;
        DateTimeFormatter dfDateTime = DateTimeFormatter.ofPattern(format);
        return dfDateTime.format(localDateTime);
    }

    /**
     * 日期时间 转localDateTime
     *
     * @param localDateTimeStr 日期时间字符串
     * @return LocalDateTime
     */
    public static LocalDateTime ofLocalDateTime(String localDateTimeStr) {
        return ofLocalDateTime(localDateTimeStr, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 日期时间 转localDateTime
     *
     * @param localDateTimeStr 日期时间字符串
     * @param format           时间格式
     * @return LocalDateTime
     */
    public static LocalDateTime ofLocalDateTime(String localDateTimeStr, String format) {
        DateTimeFormatter dfDateTime = DateTimeFormatter.ofPattern(format);

        TemporalAccessor parse = dfDateTime.parse(localDateTimeStr);
        return LocalDateTime.from(parse);
    }

    /**
     * 获取当前日期时间字符串
     *
     * @return 时间日期字符串
     */
    public static String nowStr() {
        return format(LocalDateTime.now());
    }

    /**
     * 获取当前日期时间字符串
     *
     * @param format 时间格式
     * @return 时间日期字符串
     */
    public static String nowStr(String format) {
        return format(LocalDateTime.now(), format);
    }

    /**
     * 获取时间差
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return 时间差 毫秒值
     */
    public static long timeDiffMillis(LocalDateTime startTime, LocalDateTime endTime) {
        return timeDiffMillis(startTime, endTime, true);
    }

    /**
     * 获取时间差
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param isAbs     是否只取正数
     * @return 时间差 毫秒值
     */
    public static long timeDiffMillis(LocalDateTime startTime, LocalDateTime endTime, boolean isAbs) {
        Duration duration = timeDiff(startTime, endTime);
        if (!isAbs) {
            return duration.toMillis();
        }
        return Math.abs(duration.toMillis());
    }

    /**
     * 获取时间差
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return 时间差
     */
    public static Duration timeDiff(LocalDateTime startTime, LocalDateTime endTime) {
        return Duration.between(startTime, endTime);
    }

    /**
     * LocalDateTime 转 Date
     *
     * @param localDateTime LocalDateTime
     * @return Date
     */
    public static Date toDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * LocalDateTime 转 Date
     *
     * @param localDateTime LocalDateTime
     * @param zoneId        时区
     * @return Date
     */
    public static Date toDate(LocalDateTime localDateTime, ZoneId zoneId) {
        return Date.from(localDateTime.atZone(zoneId).toInstant());
    }
}
